home *** CD-ROM | disk | FTP | other *** search
/ User's Choice Windows CD / User's Choice Windows CD (CMS Software)(1993).iso / utility1 / gs261src.zip / GDEVBJ10.C < prev    next >
C/C++ Source or Header  |  1993-05-13  |  12KB  |  343 lines

  1. /* Copyright (C) 1990, 1992, 1993 Aladdin Enterprises.  All rights reserved.
  2.  
  3. This file is part of Ghostscript.
  4.  
  5. Ghostscript is distributed in the hope that it will be useful, but
  6. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  7. to anyone for the consequences of using it or for whether it serves any
  8. particular purpose or works at all, unless he says so in writing.  Refer
  9. to the Ghostscript General Public License for full details.
  10.  
  11. Everyone is granted permission to copy, modify and redistribute
  12. Ghostscript, but only under the conditions described in the Ghostscript
  13. General Public License.  A copy of this license is supposed to have been
  14. given to you along with Ghostscript so you can know your rights and
  15. responsibilities.  It should be in a file named COPYING.  Among other
  16. things, the copyright notice and this notice must be preserved on all
  17. copies.  */
  18.  
  19. /* gdevbj10.c */
  20. /* Canon Bubble Jet BJ-10e printer driver for Ghostscript */
  21. #include "gdevprn.h"
  22.  
  23. private dev_proc_get_initial_matrix(bj_get_initial_matrix);
  24.  
  25. /*
  26.  * The only available resolutions are (180,360)x(180,360).
  27.  */
  28.  
  29. /* The device descriptor */
  30. private dev_proc_print_page(bj10e_print_page);
  31. gx_device_printer far_data gs_bj10e_device =
  32.   prn_device(prn_std_procs, "bj10e",
  33.     80,                /* width_10ths, 8" */
  34.     105,                /* height_10ths, 10.5" */
  35.     360,                /* x_dpi */
  36.     360,                /* y_dpi */
  37.     0,0,0,0,            /* margins */
  38.     1, bj10e_print_page);
  39.  
  40. /*
  41.  * The following is taken from the BJ200 Programmer's manual.  The top
  42.  * margin is 3mm (0.12"), and the bottom margin is 6.4mm (0.25").  The
  43.  * left and right margin depend on the type of paper -- US letter or
  44.  * A4 -- but ultimately rest on a print width of 203.2mm (8").  For letter
  45.  * paper, the left margin (and hence the right) is 6.4mm (0.25"), while
  46.  * for A4 paper, both are 3.4mm (0.13").
  47.  *
  48.  * The bottom margin requires a bit of care.  The image is printed
  49.  * as strips, each about 3.4mm wide.  We can only attain the bottom 
  50.  * margin if the final strip coincides with it.  Note that each strip
  51.  * is generated using only 48 of the available 64 jets, and the absence
  52.  * of those bottom 16 jets makes our bottom margin, in effect, about
  53.  * 1.1mm (0.04") larger.
  54.  *
  55.  * The bj200 behaves, in effect, as though the origin were at the first
  56.  * printable position, rather than the top left corner of the page, so
  57.  * we add a translation to the initial matrix to compensate for this.
  58.  *
  59.  * Except for the details of getting the margins correct, the bj200 is
  60.  * no different from the bj10e, and uses the same routine to print each
  61.  * page.
  62.  *
  63.  * NOTE:  The bj200 has a DIP switch called "Text scale mode" and if
  64.  * set, it allows the printer to get 66 lines on a letter-sized page
  65.  * by reducing the line spacing by a factor of 14/15.  If this DIP
  66.  * switch is set, the page image printed by ghostscript will also be
  67.  * similarly squeezed.  Thus text scale mode is something ghostscript
  68.  * would like to disable.
  69.  *
  70.  * According to the bj200 manual, which describes the bj10 commands,
  71.  * the printer can be reset either to the settings determined by the
  72.  * DIP switches, or to the factory defaults, and then some of those
  73.  * settings can be specifically overriden.  Unfortunately, the text
  74.  * scale mode and horizontal print position (for letter vs A4 paper)
  75.  * can not be overriden.  On my bj200, the factory settings are for
  76.  * no text scaling and letter paper, thus using the factory defaults
  77.  * also implies letter paper.  I don't know if this is necessarily
  78.  * true for bj200's sold elsewhere, or for other printers that use
  79.  * the same command set.
  80.  *
  81.  * If your factory defaults are in fact the same, you can compile
  82.  * the driver with USE_FACTORY_DEFAULTS defined, in which case the
  83.  * printer will be reset to the factory defaults for letter paper,
  84.  * and reset to the DIP switch settings for A4 paper.  In this case,
  85.  * with letter-sized paper, the text scale mode will be disabled.
  86.  * Further, by leaving the horizontal print position DIP switch set
  87.  * for A4 paper, gs will be able to print on either A4 or letter
  88.  * paper without changing the DIP switch.  Since it's not clear that
  89.  * the factory defaults are universal, the default behaviour is not
  90.  * to define USE_FACTORY_DEFAULTS, and the printer will always be
  91.  * reset to the DIP switch defaults.
  92.  */
  93.  
  94. #define BJ200_TOP_MARGIN        0.12
  95. #define BJ200_BOTTOM_MARGIN        0.29
  96. #define BJ200_LETTER_SIDE_MARGIN    0.25
  97. #define BJ200_A4_SIDE_MARGIN        0.13
  98.  
  99. private dev_proc_open_device(bj200_open);
  100.  
  101. gx_device_procs prn_bj200_procs =
  102.   prn_matrix_procs(bj200_open, bj_get_initial_matrix,
  103.     gdev_prn_output_page, gdev_prn_close);
  104.  
  105. gx_device_printer far_data gs_bj200_device =
  106.   prn_device(prn_bj200_procs, "bj200",
  107.     DEFAULT_WIDTH_10THS,
  108.     DEFAULT_HEIGHT_10THS,
  109.     360,                /* x_dpi */
  110.     360,                /* y_dpi */
  111.     0, 0, 0, 0,            /* margins filled in by bj200_open */
  112.     1, bj10e_print_page);
  113.  
  114. /* ------ internal routines ------ */
  115.  
  116. /* Open the printer, and set the margins. */
  117. private int
  118. bj200_open(gx_device *pdev)
  119. {       /* Change the margins according to the paper size. */
  120.  
  121.     /* The top and bottom margins don't seem to depend on the
  122.        page length, but on the paper handling mechanism. */
  123.     pdev->t_margin = BJ200_TOP_MARGIN;
  124.     pdev->b_margin = BJ200_BOTTOM_MARGIN;
  125.  
  126.     /* The side margins do depend on the paper width, as the
  127.        printer centres the 8" print line on the page. */
  128.     if ( pdev->width / pdev->x_pixels_per_inch <= 8.4 )
  129.         pdev->l_margin = pdev->r_margin = BJ200_A4_SIDE_MARGIN;
  130.     else
  131.         pdev->l_margin = pdev->r_margin = BJ200_LETTER_SIDE_MARGIN;
  132.  
  133.         return gdev_prn_open(pdev);
  134. }
  135.  
  136. /* Shift the origin from the top left corner of the pysical page to the
  137.    first printable pixel, as defined by the top and left margins. */
  138. private void
  139. bj_get_initial_matrix(gx_device *dev, gs_matrix *pmat)
  140. {    gx_default_get_initial_matrix(dev, pmat);
  141.     pmat->tx -= dev->l_margin * dev->x_pixels_per_inch;
  142.     pmat->ty -= dev->t_margin * dev->y_pixels_per_inch;
  143. }
  144.  
  145. /* Send the page to the printer. */
  146. private int
  147. bj10e_print_page(gx_device_printer *pdev, FILE *prn_stream)
  148. {    int line_size = gx_device_raster((gx_device *)pdev, 0);
  149.     int xres = pdev->x_pixels_per_inch;
  150.     int yres = pdev->y_pixels_per_inch;
  151.     int mode = (yres == 180 ?
  152.             (xres == 180 ? 11 : 12) :
  153.             (xres == 180 ? 14 : 16));
  154.     int bytes_per_column = (yres == 180) ? 3 : 6;
  155.     int bits_per_column = bytes_per_column * 8;
  156.     int skip_unit = bytes_per_column * 3;
  157.     byte *in = (byte *)gs_malloc(8, line_size, "bj10e_print_page(in)");
  158.     byte *out = (byte *)gs_malloc(bits_per_column, line_size, "bj10e_print_page(out)");
  159.     int lnum = 0;
  160.     int skip = 0;
  161.     int code = 0;
  162.     int last_row = pdev->height - (pdev->t_margin + pdev->b_margin) * yres;
  163.     int limit = last_row - bits_per_column;
  164.  
  165.     if ( in == 0 || out == 0 )
  166.     {    code = gs_error_VMerror;
  167.         gs_note_error(code);
  168.         goto fin;
  169.     }
  170.  
  171.     /* Initialize the printer. */
  172. #ifdef USE_FACTORY_DEFAULTS
  173.     /* Check for U.S. letter vs. A4 paper. */
  174.     fwrite(( pdev->width / pdev->x_pixels_per_inch <= 8.4 ?
  175.         "\033[K\004\000\000\044\000\000" /*A4--DIP switch defaults*/ :
  176.         "\033[K\004\000\004\044\000\000" /*letter--factory defaults*/ ),
  177.            1, 9, prn_stream);
  178. #else
  179.     fwrite("\033[K\004\000\000\044\000\000", 1, 9, prn_stream);
  180. #endif
  181.  
  182.     /* Set vertical spacing. */
  183.     fwrite("\033[\\\004\000\000\000", 1, 7, prn_stream);
  184.     fputc(yres & 0xff, prn_stream);
  185.     fputc(yres >> 8, prn_stream);
  186.  
  187.     /* Set the page length.  This is the printable length, in inches. */
  188.     fwrite("\033C\000", 1, 3, prn_stream);
  189.     fputc((last_row + yres - 1)/yres, prn_stream);
  190.  
  191.     /* Transfer pixels to printer.  The last row we can print is defined
  192.        by "last_row".  Only the bottom of the print head can print at the
  193.        bottom margin, and so we align the final printing pass.  The print
  194.        head is kept from moving below "limit", which is exactly one pass
  195.        above the bottom margin.  Once it reaches this limit, we make our
  196.        final printing pass of a full "bits_per_column" rows. */
  197.     while ( lnum < last_row )
  198.        {    
  199.         byte *in_data;
  200.         byte *in_end = in + line_size;
  201.         byte *out_beg = out;
  202.         byte *out_end = out + bytes_per_column * pdev->width;
  203.         byte *outl = out;
  204.         int count, bnum;
  205.  
  206.         /* Copy 1 scan line and test for all zero. */
  207.         code = gdev_prn_get_bits(pdev, lnum, in, &in_data);
  208.         if ( code < 0 ) goto xit;
  209.         /* The mem... or str... functions should be faster than */
  210.         /* the following code, but all systems seem to implement */
  211.         /* them so badly that this code is faster. */
  212.            {    register const long *zip = (const long *)in_data;
  213.             register int zcnt = line_size;
  214.             register const byte *zipb;
  215.             for ( ; zcnt >= 4 * sizeof(long); zip += 4, zcnt -= 4 * sizeof(long) )
  216.                {    if ( zip[0] | zip[1] | zip[2] | zip[3] )
  217.                     goto notz;
  218.                }
  219.             zipb = (const byte *)zip;
  220.             while ( --zcnt >= 0 )
  221.                {
  222.                 if ( *zipb++ )
  223.                     goto notz;
  224.                }
  225.             /* Line is all zero, skip */
  226.             lnum++;
  227.             skip++;
  228.             continue;
  229. notz:            ;
  230.            }
  231.  
  232.         /* Vertical tab to the appropriate position.  Note here that
  233.            we make sure we don't move below limit. */
  234.         if ( lnum > limit )
  235.             {    skip -= (limit - lnum);
  236.             lnum = limit;
  237.             }
  238.         while ( skip > 255 )
  239.            {    fputs("\033J\377", prn_stream);
  240.             skip -= 255;
  241.            }
  242.         if ( skip )
  243.             fprintf(prn_stream, "\033J%c", skip);
  244.  
  245.         /* If we've printed as far as "limit", then reset "limit"
  246.            to "last_row" for the final printing pass. */
  247.         if ( lnum == limit )
  248.             limit = last_row;
  249.         skip = 0;
  250.  
  251.         /* Transpose in blocks of 8 scan lines. */
  252.         for ( bnum = 0; bnum < bits_per_column; bnum += 8 )
  253.            {    int lcnt = min(8, limit - lnum);
  254.             byte *inp = in;
  255.             byte *outp = outl;
  256.                lcnt = gdev_prn_copy_scan_lines(pdev,
  257.                 lnum, in, lcnt * line_size);
  258.             if ( lcnt < 0 )
  259.                {    code = lcnt;
  260.                 goto xit;
  261.                }
  262.             if ( lcnt < 8 )
  263.                 memset(in + lcnt * line_size, 0,
  264.                        (8 - lcnt) * line_size);
  265.             for ( ; inp < in_end; inp++, outp += bits_per_column )
  266.                {    gdev_prn_transpose_8x8(inp, line_size,
  267.                     outp, bytes_per_column);
  268.                }
  269.             outl++;
  270.             lnum += lcnt;
  271.             skip += lcnt;
  272.            }
  273.  
  274.         /* Send the bits to the printer.  We alternate horizontal
  275.            skips with the data.  The horizontal skips are in units
  276.            of 1/120 inches, so we look at the data in groups of
  277.            3 columns, since 3/360 = 1/120, and 3/180 = 2/120.  */
  278.         outl = out;
  279.         do
  280.            {    int count;
  281.             int n;
  282.             byte *out_ptr;
  283.  
  284.             /* First look for blank groups of columns. */
  285.             while(outl < out_end)
  286.                {    n = count = min(out_end - outl, skip_unit);
  287.                 out_ptr = outl;
  288.                 while ( --count >= 0 )
  289.                    {    if ( *out_ptr++ )
  290.                         break;
  291.                    }
  292.                 if ( count >= 0 )
  293.                     break;
  294.                 else
  295.                     outl = out_ptr;
  296.                }
  297.             if (outl >= out_end)
  298.                 break;
  299.             if (outl > out_beg)
  300.                {    count = (outl - out_beg) / skip_unit;
  301.                 if ( xres == 180 ) count <<= 1;
  302.                 fprintf(prn_stream, "\033d%c%c",
  303.                     count & 0xff, count >> 8);
  304.                }
  305.  
  306.             /* Next look for non-blank groups of columns. */
  307.             out_beg = outl;
  308.             outl += n;
  309.             while(outl < out_end)
  310.                {    n = count = min(out_end - outl, skip_unit);
  311.                 out_ptr = outl;
  312.                 while ( --count >= 0 )
  313.                    {    if ( *out_ptr++ )
  314.                         break;
  315.                    }
  316.                 if ( count < 0 )
  317.                     break;
  318.                 else
  319.                     outl += n;
  320.                }
  321.             count = outl - out_beg + 1;
  322.             fprintf(prn_stream, "\033[g%c%c%c",
  323.                 count & 0xff, count >> 8, mode);
  324.             fwrite(out_beg, 1, count - 1, prn_stream);
  325.             out_beg = outl;
  326.             outl += n;
  327.            }
  328.         while ( out_beg < out_end );
  329.  
  330.         fputc('\r', prn_stream);
  331.        }
  332.  
  333.     /* Eject the page */
  334. xit:    fputc(014, prn_stream);    /* form feed */
  335.     fflush(prn_stream);
  336. fin:    if ( out != 0 )
  337.         gs_free((char *)out, bits_per_column, line_size,
  338.             "bj10e_print_page(out)");
  339.     if ( in != 0 )
  340.         gs_free((char *)in, 8, line_size, "bj10e_print_page(in)");
  341.     return code;
  342. }
  343.